/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#ifndef IMODULE_HPP
#define IMODULE_HPP

#include <map>
#include <boost/thread/mutex.hpp>
#include "cpputils/CppUtils.hpp"

namespace cpputils {
	/**
	 * Dynmod provide a support for dynamically loading shared libraries with the specific implementation based on
	 * standard API with:
	 *  - Versioning (Checking API versions)
	 *  - Standard lifecycle methods (single init & finalization library, creating an instance of object, looking up object by class name)
	 */
	namespace dynmod {

		/**
		 * IModule interface provide a support for basic module attributes
		 * and a universal factory method
		 * @sa ModulesFactory
		 */
		class IModule {
		protected:
			friend class ModulesFactory;
			virtual void addRef()=0;
			virtual bool unload()=0;
			virtual void* createModuleObjectInstance(const std::type_info& oTypeInfo)=0;
		public:
			virtual ~IModule() {};
			virtual std::string getName()=0;


			typedef IModule* Ptr;
			typedef boost::shared_ptr< IModule > SharedPtr;

			template<typename T>
			typename boost::shared_ptr< T > createModuleObject();
		};

		#include "IModule.inl"

		/**
		 * Module library activation results
		 */
		enum ActivationResult {
			ACTIVATE_TRANSPORT_MODULE_SUCCESS=0,
			ACTIVATE_TRANSPORT_MODULE_INCORRECT_API=1,
			ACTIVATE_TRANSPORT_MODULE_ENVIRONMENT_ERROR=2,
			ACTIVATE_TRANSPORT_MODULE_ILLEGAL_COMPLIANCE=3,
			ACTIVATE_TRANSPORT_MODULE_UNKNOWN=255
		};

		/**
		 * An initialization module C-function specification.
		 */
		typedef ActivationResult (*PtrDynmodInitFunc) (
			const cpputils::utils::Version& oVersion
		);

		#define DYNMOD_INIT_FUNC_NAME "dynmodInit"
		#define DYNMOD_INIT_FUNC(PRFX) \
			extern "C" PRFX cpputils::dynmod::ActivationResult dynmodInit \
				( \
					const cpputils::utils::Version& oVersion \
				)

		/**
		 * A finalization module C-function specification.
		 */
		typedef void (*PtrDynmodFinalizeFunc) ();

		#define DYNMOD_FINALIZE_FUNC_NAME "dynmodFinalize"
		#define DYNMOD_FINALIZE_FUNC(PRFX) \
			extern "C" PRFX void dynmodFinalize()

		/**
		 * A factory module C-function specification.
		 */
		typedef void* (*PtrDynmodCreateInstanceFunc) (const std::type_info& oTypeInfo);

		#define DYNMOD_CREATEINSTANCE_FUNC_NAME "dynmodCreateInstance"
		#define DYNMOD_CREATEINSTANCE_FUNC(PRFX) \
			extern "C" PRFX void* dynmodCreateInstance(const std::type_info& oTypeInfo)


	}
}

#endif // IMODULE_HPP
